package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.assistant.common.vo.SmsVO;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.data.core.util.PagerUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.enums.SendStatusEnum;
import com.jwsoft.manager.common.vo.eduSendContent.EduSendContentKeyVO;
import com.jwsoft.manager.common.vo.eduSendContent.EduSendContentQueryVO;
import com.jwsoft.manager.common.vo.eduSendContent.EduSendContentVO;
import com.jwsoft.manager.common.vo.eduSendMessageModel.EduSendMessageModelVO;
import com.jwsoft.manager.core.dao.model.EduSendContent;
import com.jwsoft.manager.core.dao.model.EduSendMessageModel;
import com.jwsoft.manager.core.dao.service.EduMessageModelParamsService;
import com.jwsoft.manager.core.dao.service.EduSendContentService;
import com.jwsoft.manager.core.dao.service.EduSendMessageModelService;
import com.jwsoft.manager.core.integration.EduSendContentIntegration;
import com.jwsoft.manager.core.integration.common.impl.EduSmsIntegrationImpl;
import com.jwsoft.manager.core.util.EduHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 短信内容结果表业务实现类
 *
 * @author zjl
 * @since 2024-06-28
 */
@ApiService(funcCode = "eduSendContent", title = "短信内容结果表")
public class EduSendContentIntegrationImpl implements EduSendContentIntegration {

    @Autowired
    public EduSendContentService eduSendContentService;
    @Autowired
    public EduHelper eduHelper;
    @Autowired
    public EduSmsIntegrationImpl eduSmsIntegration;
    @Autowired
    public EduMessageModelParamsService eduMessageModelParamsService;
    @Autowired
    public EduSendMessageModelService eduSendMessageModelService;

    @Override
    @OpApi(funcCode = "eduSendContent0001", title = "短信内容结果表分页查询", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public PageInfo<EduSendContentVO> getList(EduSendContentQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        PageHelper.startPage(vo.getPageNum(),vo.getPageSize());
        LambdaQueryWrapper<EduSendContent> queryWrapper = new QueryWrapper<EduSendContent>()
                .lambda()
                .eq(StringUtils.isNotBlank(vo.getFullName()), EduSendContent::getFullName, vo.getFullName())
                .eq(StringUtils.isNotBlank(vo.getAreaCode()), EduSendContent::getAreaCode, vo.getAreaCode())
                .eq(StringUtils.isNotBlank(vo.getTelephone()), EduSendContent::getTelephone, vo.getTelephone())
                .eq(StringUtils.isNotBlank(vo.getSendStatus()), EduSendContent::getSendStatus, vo.getSendStatus())
                .eq(StringUtils.isNotBlank(vo.getMessageModelId()), EduSendContent::getMessageModelId, vo.getMessageModelId());
        List<EduSendContent> list = eduSendContentService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduSendContent> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduSendContentVO> resultList = Convert.toList(EduSendContentVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduSendContent0002", title = "短信内容结果表根据主键查询详情", funcType = FuncTypeEnum.query,checkPrivilege = BoolEnum.FALSE)
    public EduSendContentVO getById(EduSendContentKeyVO vo) {
        EduSendContent entity = eduSendContentService.getById(vo.getContentId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduSendContentVO result = Convert.convert(EduSendContentVO.class, entity);
        return result;
    }
    /** 保存前统一校验*/
    @Override
    @OpApi(funcCode = "eduSendContent0003", title = "短信内容结果表保存前校验", funcType = FuncTypeEnum.other ,checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduSendContentVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "eduSendContent0004", title = "短信内容结果表新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduSendContent0004",
            operationName = "短信内容结果表新增",
            dataType = "contentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSendContentVO add(EduSendContentVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSendContent entity = Convert.convert(EduSendContent.class, vo);
        eduSendContentService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setContentId(entity.getContentId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduSendContent0005", title = "短信内容结果表修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "eduSendContent0005",
            operationName = "短信内容结果表修改",
            dataType = "contentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduSendContentVO edit(EduSendContentVO vo) {
        if (ObjectUtils.isEmpty(vo.getContentId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduSendContent oldEntity = eduSendContentService.getById(vo.getContentId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduSendContent entity = Convert.convert(EduSendContent.class, vo);
        eduSendContentService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduSendContent0006", title = "短信内容结果表根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "eduSendContent0006",
            operationName = "短信内容结果表删除",
            dataType = "contentId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduSendContentKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getContentId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduSendContent entity = eduSendContentService.getById(vo.getContentId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduSendContentService.removeById(vo.getContentId());
    }

    @Override
    @OpApi(funcCode = "eduSendContent0007", title = "发送单条短信", funcType = FuncTypeEnum.other)
    @SaveOplog(operationType = "eduSendContent0007", operationName = "发送单条短信", dataType = "contentId", auType = AuTypeEnum.OTHER)
    @Transactional
    public boolean sendSingleMessage(EduSendContentQueryVO vo) {
        if (ObjectUtils.isEmpty(vo.getContentId())) {
            throw new AppException("主键不能为空!");
        }
        LambdaQueryWrapper<EduSendContent> queryWrapper = new QueryWrapper<EduSendContent>().lambda()
                .eq(EduSendContent::getContentId, vo.getContentId())
                .eq(EduSendContent::getSendStatus, SendStatusEnum.dfs.getType())
                .eq(EduSendContent::getYear, eduHelper.thisYear());
        EduSendContent entity = eduSendContentService.getOne(queryWrapper,false);
        if (ObjectUtils.isEmpty(entity)){
            throw new AppException("未查询到数据");
        }
        boolean send=false;
        if (entity.getSendStatus().equalsIgnoreCase(SendStatusEnum.dfs.getType())){
            int errorCount = 0;
            while (errorCount < 3){
                SmsVO smsVO = new SmsVO();
                smsVO.setPhone(entity.getTelephone());
                smsVO.setMessage(entity.getContent());
                try {
                    send= eduSmsIntegration.send(smsVO);
                    if (send){
                        entity.setSendStatus(SendStatusEnum.yfs.getType());
                        eduSendContentService.updateById(entity);
                        return send;
                    }
                }catch (Exception e){
                    errorCount++;
                    //3次发送都失败
                    if (errorCount >= 3){
                        entity.setSendStatus(SendStatusEnum.fssb.getType());
                        entity.setRemarks(e.getMessage());
                        eduSendContentService.updateById(entity);
                        break;
                    }
                }
            }
        }else{
            throw new AppException("短信状态不是待发送状态不能发送");
        }
        return send;
    }

    @Override
    @OpApi(funcCode = "eduSendContent0008", title = "查询短信编号", funcType = FuncTypeEnum.query)
    public List<EduSendMessageModelVO> queryMessageNumber(EduSendContentQueryVO vo) {
        QueryWrapper<EduSendMessageModel> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduSendMessageModel::getYear, eduHelper.thisYear());
        List<EduSendMessageModel> modelParamsList = eduSendMessageModelService.list(queryWrapper);
        List<EduSendMessageModel> modelParams = modelParamsList.stream().distinct().collect(Collectors.toList());
        return Convert.toList(EduSendMessageModelVO.class,modelParams);
    }

    @Override
    @OpApi(funcCode = "eduSendContent0009", title = "批量修改短信状态", funcType = FuncTypeEnum.update)
    @SaveOplog(operationType = "eduSendContent0009", operationName = "批量修改短信状态", dataType = "contentId", auType = AuTypeEnum.OTHER)
    @Transactional
    public void batchUpdateMessageStatus(EduSendContentQueryVO vo) {
        if (CollectionUtils.isEmpty(vo.getContentIdList())){
            throw new AppException("选择数据id不能为空!");
        }
        EduSendContentVO contentVO = Convert.convert(EduSendContentVO.class, vo);
        for (String contentId : vo.getContentIdList()){
            contentVO.setContentId(contentId);
            this.editMessageStatus(contentVO);
        }
    }

    @Override
    public void editMessageStatus(EduSendContentVO vo) {
        EduSendContent eduSendContent = eduSendContentService.getById(vo.getContentId());
        if (ObjectUtils.isEmpty(eduSendContent)) {
            throw new AppException("未查询到数据");
        }
        if (!eduSendContent.getSendStatus().equalsIgnoreCase(SendStatusEnum.cg.getType())){
            throw new AppException("短信状态不是草稿状态不能一键到待发送");
        }
        eduSendContent.setSendStatus(SendStatusEnum.dfs.getType());
        eduSendContentService.saveOrUpdate(eduSendContent);
    }

    @Override
    @OpApi(funcCode = "eduSendContent0010", title = "批量发送短信", funcType = FuncTypeEnum.other)
    @SaveOplog(operationType = "eduSendContent0010", operationName = "批量发送短信", dataType = "contentId", auType = AuTypeEnum.OTHER)
    @Transactional
    public void batchSendMessage(EduSendContentQueryVO vo) {
        if (CollectionUtils.isEmpty(vo.getContentIdList())){
            throw new AppException("选择数据id不能为空!");
        }
        for (String contentId : vo.getContentIdList()){
            vo.setContentId(contentId);
            this.sendSingleMessage(vo);
        }
    }

    @Override
    public void sendMessageTest(EduSendContentQueryVO vo) {
        this.timerSendMessage(vo);
    }

    @Override
    public void timerSendMessage(EduSendContentQueryVO vo) {
        if (StringUtils.isBlank(vo.getMessageModelNum())){
            throw new AppException("短信模板编号不能为空!");
        }
        LambdaQueryWrapper<EduSendMessageModel> queryWrapper = new QueryWrapper<EduSendMessageModel>().lambda()
                .eq(EduSendMessageModel::getMessageModelNum, vo.getMessageModelNum())
                .eq(EduSendMessageModel::getYear, eduHelper.thisYear());
        EduSendMessageModel messageModel = eduSendMessageModelService.getOne(queryWrapper, false);
        if (ObjectUtils.isEmpty(messageModel)){
            throw new AppException("未查询到短信模板");
        }
        if (StringUtils.isNotBlank(messageModel.getMessageModelId())){
            LambdaQueryWrapper<EduSendContent> wrapper = new QueryWrapper<EduSendContent>().lambda()
                    .eq(EduSendContent::getMessageModelId, messageModel.getMessageModelId())
                    .eq(EduSendContent::getSendStatus, SendStatusEnum.dfs.getType())
                    .eq(EduSendContent::getYear, eduHelper.thisYear());
            List<EduSendContent> contentList = eduSendContentService.list(wrapper);
            if (!CollectionUtils.isEmpty(contentList)){
                for (EduSendContent content : contentList){
                    if (!content.getSendStatus().equalsIgnoreCase(SendStatusEnum.dfs.getType())){
                        throw new AppException("不是待发送状态不能发送短信");
                    }
                    EduSendContentQueryVO sendContentVO = Convert.convert(EduSendContentQueryVO.class, content);
                    if (StringUtils.isNotBlank(content.getSendStartTime()) && StringUtils.isNotBlank(content.getSendEndTime())){
                        LocalDateTime sendStartTime = this.handleTime(content.getSendStartTime());
                        LocalDateTime sendEndTime = this.handleTime(content.getSendEndTime());
                        LocalDateTime nowTime = LocalDateTime.now();
                        //在模板时间范围内可发送短信
                        if (!nowTime.isBefore(sendStartTime) && !nowTime.isAfter(sendEndTime)){
                            this.sendSingleMessage(sendContentVO);
                        }
                    }else{
                        this.sendSingleMessage(sendContentVO);
                    }
                }
            }
        }
    }
    private  LocalDateTime handleTime(String timeStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        LocalTime time = LocalTime.parse(timeStr, formatter);
        LocalDate today = LocalDate.now();
        LocalDateTime dateTime = LocalDateTime.of(today, time);
        return dateTime;
    }
}
